package elementaryAlgorithm;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 郭辉
 * @className TODO
 * @description 105. 从前序与中序遍历序列构造二叉树
 * 给定两个整数数组 preorder 和 inorder ，其中 preorder 是二叉树的先序遍历， inorder 是同一棵树的中序遍历，请构造二叉树并返回其根节点。
 *
 *
 *
 * 示例 1:
 *
 *
 * 输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
 * 输出: [3,9,20,null,null,15,7]
 * 示例 2:
 *
 * 输入: preorder = [-1], inorder = [-1]
 * 输出: [-1]
 *
 *
 * 提示:
 *
 * 1 <= preorder.length <= 3000
 * inorder.length == preorder.length
 * -3000 <= preorder[i], inorder[i] <= 3000
 * preorder 和 inorder 均 无重复 元素
 * inorder 均出现在 preorder
 * preorder 保证 为二叉树的前序遍历序列
 * inorder 保证 为二叉树的中序遍历序列
 * 通过次数471,487提交次数660,315
 * @date 2023/3/15 19:45
 * @company 海康威视
 * @since 1.0.0
 */
public class Leet105 {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        Map<Integer,Integer> midIndexMAP = new HashMap<>();
        Map<Integer,Boolean> midVisitMAP = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) {
            midIndexMAP.put(inorder[i],i);
            midVisitMAP.put(i,false);
        }
        TreeNode root = new TreeNode(preorder[0]);
        midVisitMAP.put(midIndexMAP.get(preorder[0]),true);
        List<Integer> list = new ArrayList<>(0);
        list.add(0);
        TreeNode node = buildTreeT(root, midIndexMAP, midVisitMAP, list, preorder, inorder);
        return node;
    }

    private TreeNode buildTreeT(TreeNode node, Map<Integer, Integer> midIndexMAP, Map<Integer, Boolean> midVisitMAP, List<Integer> l, int[] preorder, int[] inorder) {

        //node 在中序中的左右都访问了，返回
        if (( midIndexMAP.get(node.val)==0 || midVisitMAP.get(midIndexMAP.get(node.val)-1) == true)
                && ( midIndexMAP.get(node.val)==inorder.length-1 || midVisitMAP.get(midIndexMAP.get(node.val) +1) == true)){
            return node;
        }
        //构建左子树
        if (midIndexMAP.get(node.val)!=0 &&  midVisitMAP.get(midIndexMAP.get(node.val)-1) == false){
            l.set(0,l.get(0)+1);
            midVisitMAP.put(midIndexMAP.get(preorder[l.get(0)]),true);
            node.left = buildTreeT(new TreeNode(preorder[l.get(0)]),midIndexMAP,midVisitMAP,l,preorder,inorder);
        }
        //构建右子树
        if (midIndexMAP.get(node.val)!=inorder.length-1 && midVisitMAP.get(midIndexMAP.get(node.val)+1) == false){
            l.set(0,l.get(0)+1);
            midVisitMAP.put(midIndexMAP.get(preorder[l.get(0)]),true);
            node.right = buildTreeT(new TreeNode(preorder[l.get(0)]),midIndexMAP,midVisitMAP,l,preorder,inorder);
        }
        return node;
    }

    public static void main(String[] args) {
        Leet105 leet105 = new Leet105();
        int[] preorder = {3,1,2,4}, inorder = {1,2,3,4};
        TreeNode node = leet105.buildTree(preorder, inorder);
        System.out.println(leet105.buildTree(preorder, inorder));

    }
}
